package com.yhos.platform.oopston.core.logback;

import ch.qos.logback.classic.AsyncAppender;
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.yhos.platform.oopston.core.manager.TraceConstant;
import com.yhos.platform.oopston.core.manager.TraceParameterThreadLocalManager;
import org.slf4j.MDC;

import java.util.Map;
import java.util.UUID;

/**
 * 集成AsyncAppender重写日志预处理阶段，将上下文请求线程中获取Header信息，并将这部分信息传入到Self4J的MDC中，
 * 通过LogbackMDCAdapter将Header信息传入到MDC中并保存在LoggingEvent里
 */
public class TraceAsyncAppender extends AsyncAppender {

    private TraceParameterThreadLocalManager traceParameterThreadLocalManager = TraceParameterThreadLocalManager.getInstance();

    private String fromSource;

    protected void preprocess(ILoggingEvent eventObject) {
        // 每次AsyncAppender日志的时候需要清空MDC，防止ThreadLocal线程重用以及内存溢出
        MDC.clear();
        if (traceParameterThreadLocalManager != null
                && traceParameterThreadLocalManager.getParams() != null
                && traceParameterThreadLocalManager.getParams().getTraceParamsMap() != null
                && traceParameterThreadLocalManager.getParams().getTraceParamsMap().size() > 0) {
            // 通过正常请求进来的所有日志，正常情况下都会取到请求上下文
            Map<String, Object> requestMap = traceParameterThreadLocalManager.getParams().getTraceParamsMap();
            for (Map.Entry<String, Object> entry : requestMap.entrySet()) {
                MDC.put(entry.getKey(), (String) entry.getValue());
            }
        } else {
            // 非请求进入的所有日志，例如启动或者运行过程的系统级别日志，如果没有上下文请求的情况下，会有默认格式
            MDC.put(TraceConstant.FROM_SOURCE, this.getFromSource());
            MDC.put(TraceConstant.FROM_SOURCE_ID, UUID.randomUUID().toString());
            MDC.put(TraceConstant.REQUEST_IP, null);
        }
        super.preprocess(eventObject);
    }

    public void setFromSource(String fromSource) {
        this.fromSource = fromSource;
    }

    public String getFromSource() {
        return fromSource;
    }

}
